"""
通知服务
负责邮件通知、系统消息等功能
"""

import smtplib
import logging
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from typing import Dict, Any, List, Optional
from datetime import datetime
from jinja2 import Template
from ..utils.redis_utils import RedisUtils

logger = logging.getLogger(__name__)

class NotificationService:
    """通知服务类"""
    
    def __init__(self, app=None):
        self.app = app
        self.redis_utils = RedisUtils(app) if app else None
        
        # 邮件配置
        if app:
            self.smtp_server = app.config.get('SMTP_SERVER')
            self.smtp_port = app.config.get('SMTP_PORT', 587)
            self.smtp_username = app.config.get('SMTP_USERNAME')
            self.smtp_password = app.config.get('SMTP_PASSWORD')
            self.smtp_use_tls = app.config.get('SMTP_USE_TLS', True)
            self.from_email = app.config.get('FROM_EMAIL', self.smtp_username)
            self.from_name = app.config.get('FROM_NAME', 'MD2DocKit')
        else:
            self.smtp_server = None
            self.smtp_port = 587
            self.smtp_username = None
            self.smtp_password = None
            self.smtp_use_tls = True
            self.from_email = None
            self.from_name = 'MD2DocKit'
    
    def send_email(self, to_email: str, subject: str, content: str, 
                   content_type: str = 'html', attachments: List[Dict] = None) -> Dict[str, Any]:
        """
        发送邮件
        
        Args:
            to_email: 收件人邮箱
            subject: 邮件主题
            content: 邮件内容
            content_type: 内容类型 ('html' 或 'plain')
            attachments: 附件列表
            
        Returns:
            发送结果
        """
        try:
            if not self._is_email_configured():
                logger.warning("邮件服务未配置，跳过发送")
                return {'success': False, 'error': '邮件服务未配置'}
            
            # 创建邮件消息
            msg = MIMEMultipart()
            msg['From'] = f"{self.from_name} <{self.from_email}>"
            msg['To'] = to_email
            msg['Subject'] = subject
            
            # 添加邮件内容
            msg.attach(MIMEText(content, content_type, 'utf-8'))
            
            # 添加附件
            if attachments:
                for attachment in attachments:
                    self._add_attachment(msg, attachment)
            
            # 发送邮件
            with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
                if self.smtp_use_tls:
                    server.starttls()
                
                server.login(self.smtp_username, self.smtp_password)
                server.send_message(msg)
            
            logger.info(f"邮件发送成功: {to_email} - {subject}")
            
            return {'success': True, 'message': '邮件发送成功'}
            
        except Exception as e:
            logger.error(f"邮件发送失败 {to_email}: {str(e)}")
            return {'success': False, 'error': f'邮件发送失败: {str(e)}'}
    
    def send_task_completion_notification(self, user_email: str, task_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        发送任务完成通知
        
        Args:
            user_email: 用户邮箱
            task_data: 任务数据
            
        Returns:
            发送结果
        """
        try:
            template_content = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8">
                <title>任务完成通知</title>
                <style>
                    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                    .header { background: #4CAF50; color: white; padding: 20px; text-align: center; }
                    .content { padding: 20px; background: #f9f9f9; }
                    .task-info { background: white; padding: 15px; margin: 10px 0; border-radius: 5px; }
                    .footer { text-align: center; padding: 20px; color: #666; font-size: 12px; }
                    .button { display: inline-block; padding: 10px 20px; background: #4CAF50; color: white; text-decoration: none; border-radius: 5px; }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="header">
                        <h1>🎉 任务完成通知</h1>
                    </div>
                    <div class="content">
                        <p>您好！</p>
                        <p>您的文档转换任务已成功完成：</p>
                        
                        <div class="task-info">
                            <h3>任务详情</h3>
                            <p><strong>任务ID：</strong>{{ task_id }}</p>
                            <p><strong>文件名：</strong>{{ filename }}</p>
                            <p><strong>输出格式：</strong>{{ output_format }}</p>
                            <p><strong>完成时间：</strong>{{ completed_at }}</p>
                            {% if download_url %}
                            <p><strong>下载链接：</strong><a href="{{ download_url }}" class="button">立即下载</a></p>
                            {% endif %}
                        </div>
                        
                        <p>感谢您使用 MD2DocKit 文档转换服务！</p>
                    </div>
                    <div class="footer">
                        <p>此邮件由系统自动发送，请勿回复。</p>
                        <p>© 2024 MD2DocKit. All rights reserved.</p>
                    </div>
                </div>
            </body>
            </html>
            """
            
            template = Template(template_content)
            content = template.render(
                task_id=task_data.get('task_id', ''),
                filename=task_data.get('filename', ''),
                output_format=task_data.get('output_format', '').upper(),
                completed_at=task_data.get('completed_at', datetime.utcnow()).strftime('%Y-%m-%d %H:%M:%S'),
                download_url=task_data.get('download_url', '')
            )
            
            subject = f"[MD2DocKit] 任务完成 - {task_data.get('filename', '')}"
            
            return self.send_email(user_email, subject, content, 'html')
            
        except Exception as e:
            logger.error(f"发送任务完成通知失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_task_failed_notification(self, user_email: str, task_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        发送任务失败通知
        
        Args:
            user_email: 用户邮箱
            task_data: 任务数据
            
        Returns:
            发送结果
        """
        try:
            template_content = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8">
                <title>任务失败通知</title>
                <style>
                    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                    .header { background: #f44336; color: white; padding: 20px; text-align: center; }
                    .content { padding: 20px; background: #f9f9f9; }
                    .task-info { background: white; padding: 15px; margin: 10px 0; border-radius: 5px; }
                    .error-info { background: #ffebee; padding: 15px; margin: 10px 0; border-radius: 5px; border-left: 4px solid #f44336; }
                    .footer { text-align: center; padding: 20px; color: #666; font-size: 12px; }
                    .button { display: inline-block; padding: 10px 20px; background: #2196F3; color: white; text-decoration: none; border-radius: 5px; }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="header">
                        <h1>❌ 任务失败通知</h1>
                    </div>
                    <div class="content">
                        <p>您好！</p>
                        <p>很抱歉，您的文档转换任务执行失败：</p>
                        
                        <div class="task-info">
                            <h3>任务详情</h3>
                            <p><strong>任务ID：</strong>{{ task_id }}</p>
                            <p><strong>文件名：</strong>{{ filename }}</p>
                            <p><strong>输出格式：</strong>{{ output_format }}</p>
                            <p><strong>失败时间：</strong>{{ failed_at }}</p>
                        </div>
                        
                        {% if error_message %}
                        <div class="error-info">
                            <h3>错误信息</h3>
                            <p>{{ error_message }}</p>
                        </div>
                        {% endif %}
                        
                        <p>建议您检查文件格式是否正确，或联系技术支持获取帮助。</p>
                        <p><a href="#" class="button">重新尝试</a></p>
                    </div>
                    <div class="footer">
                        <p>此邮件由系统自动发送，请勿回复。</p>
                        <p>© 2024 MD2DocKit. All rights reserved.</p>
                    </div>
                </div>
            </body>
            </html>
            """
            
            template = Template(template_content)
            content = template.render(
                task_id=task_data.get('task_id', ''),
                filename=task_data.get('filename', ''),
                output_format=task_data.get('output_format', '').upper(),
                failed_at=task_data.get('failed_at', datetime.utcnow()).strftime('%Y-%m-%d %H:%M:%S'),
                error_message=task_data.get('error_message', '')
            )
            
            subject = f"[MD2DocKit] 任务失败 - {task_data.get('filename', '')}"
            
            return self.send_email(user_email, subject, content, 'html')
            
        except Exception as e:
            logger.error(f"发送任务失败通知失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_welcome_email(self, user_email: str, username: str) -> Dict[str, Any]:
        """
        发送欢迎邮件
        
        Args:
            user_email: 用户邮箱
            username: 用户名
            
        Returns:
            发送结果
        """
        try:
            template_content = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8">
                <title>欢迎使用 MD2DocKit</title>
                <style>
                    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                    .header { background: #2196F3; color: white; padding: 20px; text-align: center; }
                    .content { padding: 20px; background: #f9f9f9; }
                    .feature { background: white; padding: 15px; margin: 10px 0; border-radius: 5px; }
                    .footer { text-align: center; padding: 20px; color: #666; font-size: 12px; }
                    .button { display: inline-block; padding: 10px 20px; background: #4CAF50; color: white; text-decoration: none; border-radius: 5px; }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="header">
                        <h1>🎉 欢迎使用 MD2DocKit</h1>
                    </div>
                    <div class="content">
                        <p>亲爱的 {{ username }}，</p>
                        <p>欢迎加入 MD2DocKit 文档转换平台！我们很高兴为您提供专业的文档转换服务。</p>
                        
                        <div class="feature">
                            <h3>🚀 主要功能</h3>
                            <ul>
                                <li>支持 Markdown 转换为多种格式（PDF、DOCX、HTML等）</li>
                                <li>实时转换进度跟踪</li>
                                <li>自定义模板和样式</li>
                                <li>批量文件处理</li>
                                <li>云端存储和管理</li>
                            </ul>
                        </div>
                        
                        <div class="feature">
                            <h3>📋 使用指南</h3>
                            <ol>
                                <li>上传您的 Markdown 文件</li>
                                <li>选择输出格式和模板</li>
                                <li>点击开始转换</li>
                                <li>下载转换后的文件</li>
                            </ol>
                        </div>
                        
                        <p style="text-align: center;">
                            <a href="#" class="button">立即开始使用</a>
                        </p>
                        
                        <p>如果您有任何问题或建议，请随时联系我们的技术支持团队。</p>
                    </div>
                    <div class="footer">
                        <p>此邮件由系统自动发送，请勿回复。</p>
                        <p>© 2024 MD2DocKit. All rights reserved.</p>
                    </div>
                </div>
            </body>
            </html>
            """
            
            template = Template(template_content)
            content = template.render(username=username)
            
            subject = "欢迎使用 MD2DocKit 文档转换平台"
            
            return self.send_email(user_email, subject, content, 'html')
            
        except Exception as e:
            logger.error(f"发送欢迎邮件失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_password_reset_email(self, user_email: str, username: str, reset_url: str) -> Dict[str, Any]:
        """
        发送密码重置邮件
        
        Args:
            user_email: 用户邮箱
            username: 用户名
            reset_url: 重置链接
            
        Returns:
            发送结果
        """
        try:
            template_content = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8">
                <title>密码重置</title>
                <style>
                    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
                    .container { max-width: 600px; margin: 0 auto; padding: 20px; }
                    .header { background: #FF9800; color: white; padding: 20px; text-align: center; }
                    .content { padding: 20px; background: #f9f9f9; }
                    .warning { background: #fff3cd; padding: 15px; margin: 10px 0; border-radius: 5px; border-left: 4px solid #FF9800; }
                    .footer { text-align: center; padding: 20px; color: #666; font-size: 12px; }
                    .button { display: inline-block; padding: 10px 20px; background: #f44336; color: white; text-decoration: none; border-radius: 5px; }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="header">
                        <h1>🔐 密码重置</h1>
                    </div>
                    <div class="content">
                        <p>亲爱的 {{ username }}，</p>
                        <p>我们收到了您的密码重置请求。如果这不是您本人的操作，请忽略此邮件。</p>
                        
                        <div class="warning">
                            <h3>⚠️ 安全提醒</h3>
                            <p>此重置链接将在 1 小时后失效，请尽快完成密码重置。</p>
                        </div>
                        
                        <p style="text-align: center;">
                            <a href="{{ reset_url }}" class="button">重置密码</a>
                        </p>
                        
                        <p>如果按钮无法点击，请复制以下链接到浏览器地址栏：</p>
                        <p style="word-break: break-all; background: #f0f0f0; padding: 10px; border-radius: 5px;">{{ reset_url }}</p>
                        
                        <p>为了您的账户安全，请不要将此链接分享给他人。</p>
                    </div>
                    <div class="footer">
                        <p>此邮件由系统自动发送，请勿回复。</p>
                        <p>© 2024 MD2DocKit. All rights reserved.</p>
                    </div>
                </div>
            </body>
            </html>
            """
            
            template = Template(template_content)
            content = template.render(username=username, reset_url=reset_url)
            
            subject = "[MD2DocKit] 密码重置请求"
            
            return self.send_email(user_email, subject, content, 'html')
            
        except Exception as e:
            logger.error(f"发送密码重置邮件失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def send_system_notification(self, user_id: str, title: str, message: str, 
                               notification_type: str = 'info') -> Dict[str, Any]:
        """
        发送系统通知
        
        Args:
            user_id: 用户ID
            title: 通知标题
            message: 通知内容
            notification_type: 通知类型 ('info', 'success', 'warning', 'error')
            
        Returns:
            发送结果
        """
        try:
            if not self.redis_utils:
                return {'success': False, 'error': 'Redis未配置'}
            
            notification = {
                'id': f"notif_{datetime.utcnow().timestamp()}",
                'title': title,
                'message': message,
                'type': notification_type,
                'created_at': datetime.utcnow().isoformat(),
                'read': False
            }
            
            # 存储到Redis
            key = f"notifications:{user_id}"
            self.redis_utils.lpush(key, notification)
            
            # 保留最近100条通知
            self.redis_utils.ltrim(key, 0, 99)
            
            # 设置过期时间（30天）
            self.redis_utils.expire(key, 30 * 24 * 3600)
            
            logger.info(f"系统通知发送成功: {user_id} - {title}")
            
            return {'success': True, 'notification_id': notification['id']}
            
        except Exception as e:
            logger.error(f"发送系统通知失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def get_user_notifications(self, user_id: str, limit: int = 20, 
                              offset: int = 0) -> Dict[str, Any]:
        """
        获取用户通知
        
        Args:
            user_id: 用户ID
            limit: 返回数量限制
            offset: 偏移量
            
        Returns:
            通知列表
        """
        try:
            if not self.redis_utils:
                return {'success': False, 'error': 'Redis未配置'}
            
            key = f"notifications:{user_id}"
            notifications = self.redis_utils.lrange(key, offset, offset + limit - 1)
            
            return {
                'success': True,
                'notifications': notifications,
                'total': self.redis_utils.llen(key)
            }
            
        except Exception as e:
            logger.error(f"获取用户通知失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def mark_notification_read(self, user_id: str, notification_id: str) -> Dict[str, Any]:
        """
        标记通知为已读
        
        Args:
            user_id: 用户ID
            notification_id: 通知ID
            
        Returns:
            操作结果
        """
        try:
            if not self.redis_utils:
                return {'success': False, 'error': 'Redis未配置'}
            
            key = f"notifications:{user_id}"
            notifications = self.redis_utils.lrange(key, 0, -1)
            
            # 查找并更新通知
            for i, notification in enumerate(notifications):
                if notification.get('id') == notification_id:
                    notification['read'] = True
                    self.redis_utils.lset(key, i, notification)
                    return {'success': True}
            
            return {'success': False, 'error': '通知不存在'}
            
        except Exception as e:
            logger.error(f"标记通知已读失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def clear_user_notifications(self, user_id: str) -> Dict[str, Any]:
        """
        清空用户通知
        
        Args:
            user_id: 用户ID
            
        Returns:
            操作结果
        """
        try:
            if not self.redis_utils:
                return {'success': False, 'error': 'Redis未配置'}
            
            key = f"notifications:{user_id}"
            self.redis_utils.delete(key)
            
            return {'success': True, 'message': '通知已清空'}
            
        except Exception as e:
            logger.error(f"清空用户通知失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def _add_attachment(self, msg: MIMEMultipart, attachment: Dict[str, Any]):
        """添加邮件附件"""
        try:
            filename = attachment.get('filename')
            content = attachment.get('content')
            content_type = attachment.get('content_type', 'application/octet-stream')
            
            if not filename or not content:
                return
            
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(content)
            encoders.encode_base64(part)
            
            part.add_header(
                'Content-Disposition',
                f'attachment; filename= {filename}'
            )
            
            msg.attach(part)
            
        except Exception as e:
            logger.error(f"添加邮件附件失败: {str(e)}")
    
    def _is_email_configured(self) -> bool:
        """检查邮件服务是否已配置"""
        return all([
            self.smtp_server,
            self.smtp_username,
            self.smtp_password,
            self.from_email
        ])
    
    def send_bulk_notification(self, user_ids: List[str], title: str, 
                              message: str, notification_type: str = 'info') -> Dict[str, Any]:
        """
        批量发送系统通知
        
        Args:
            user_ids: 用户ID列表
            title: 通知标题
            message: 通知内容
            notification_type: 通知类型
            
        Returns:
            发送结果
        """
        try:
            success_count = 0
            failed_count = 0
            
            for user_id in user_ids:
                result = self.send_system_notification(user_id, title, message, notification_type)
                if result['success']:
                    success_count += 1
                else:
                    failed_count += 1
            
            return {
                'success': True,
                'total': len(user_ids),
                'success_count': success_count,
                'failed_count': failed_count
            }
            
        except Exception as e:
            logger.error(f"批量发送通知失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    def get_notification_statistics(self) -> Dict[str, Any]:
        """
        获取通知统计信息
        
        Returns:
            统计信息
        """
        try:
            if not self.redis_utils:
                return {'success': False, 'error': 'Redis未配置'}
            
            # 获取所有通知键
            keys = self.redis_utils.keys("notifications:*")
            
            total_notifications = 0
            total_users = len(keys)
            
            for key in keys:
                total_notifications += self.redis_utils.llen(key)
            
            return {
                'success': True,
                'statistics': {
                    'total_users_with_notifications': total_users,
                    'total_notifications': total_notifications,
                    'average_notifications_per_user': total_notifications / total_users if total_users > 0 else 0
                }
            }
            
        except Exception as e:
            logger.error(f"获取通知统计失败: {str(e)}")
            return {'success': False, 'error': str(e)}